{
  "nbformat": 4,
  "nbformat_minor": 0,
  "metadata": {
    "accelerator": "GPU",
    "colab": {
      "name": "Recommending_products",
      "provenance": [],
      "collapsed_sections": []
    },
    "kernelspec": {
      "display_name": "Python 3",
      "name": "python3"
    }
  },
  "cells": [
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "NmAgD1Ta057u"
      },
      "source": [
        "Dataset\n",
        "----------\n",
        "http://cseweb.ucsd.edu/~jmcauley/datasets.html#goodreads\n",
        "* Items:\t1,561,465\n",
        "* Users:\t808,749\n",
        "* Interactions:\t225,394,930\n",
        "\n",
        "```json\n",
        "{\n",
        "  \"user_id\": \"8842281e1d1347389f2ab93d60773d4d\",\n",
        "  \"book_id\": \"130580\",\n",
        "  \"review_id\": \"330f9c153c8d3347eb914c06b89c94da\",\n",
        "  \"isRead\": true,\n",
        "  \"rating\": 4,\n",
        "  \"date_added\": \"Mon Aug 01 13:41:57 -0700 2011\",\n",
        "  \"date_updated\": \"Mon Aug 01 13:42:41 -0700 2011\",\n",
        "  \"read_at\": \"Fri Jan 01 00:00:00 -0800 1988\",\n",
        "  \"started_at\": \"\"\n",
        "}\n",
        "```\n",
        "\n",
        "see also https://snap.stanford.edu/data/amazon-meta.html\n",
        "\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "ch-tCyn66gPI",
        "outputId": "197ba60c-cee2-4dee-bd6b-592a919596f1",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 258
        }
      },
      "source": [
        "pip install git+https://github.com/maciejkula/spotlight.git"
      ],
      "execution_count": null,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "Collecting git+https://github.com/maciejkula/spotlight.git\n",
            "  Cloning https://github.com/maciejkula/spotlight.git to /tmp/pip-req-build-myzn2a4l\n",
            "  Running command git clone -q https://github.com/maciejkula/spotlight.git /tmp/pip-req-build-myzn2a4l\n",
            "Requirement already satisfied: torch>=0.4.0 in /usr/local/lib/python3.6/dist-packages (from spotlight==0.1.6) (1.6.0+cu101)\n",
            "Requirement already satisfied: numpy in /usr/local/lib/python3.6/dist-packages (from torch>=0.4.0->spotlight==0.1.6) (1.18.5)\n",
            "Requirement already satisfied: future in /usr/local/lib/python3.6/dist-packages (from torch>=0.4.0->spotlight==0.1.6) (0.16.0)\n",
            "Building wheels for collected packages: spotlight\n",
            "  Building wheel for spotlight (setup.py) ... \u001b[?25l\u001b[?25hdone\n",
            "  Created wheel for spotlight: filename=spotlight-0.1.6-cp36-none-any.whl size=33919 sha256=320c36fcaffb21d494d593397c529c6c75804929542b337f01d5607e3c1598f7\n",
            "  Stored in directory: /tmp/pip-ephem-wheel-cache-fdvnpz7v/wheels/0a/33/c8/e8510ea648aaacf6031e128dfa92bcd3750f02db2aaf0922fe\n",
            "Successfully built spotlight\n",
            "Installing collected packages: spotlight\n",
            "Successfully installed spotlight-0.1.6\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "fyJ0Beol6jqd"
      },
      "source": [
        "from spotlight.datasets.goodbooks import get_goodbooks_dataset, _get_dataset\n",
        "from spotlight.interactions import Interactions\n"
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "o11d-z9xW23o",
        "outputId": "70de19f0-96e1-4929-ee99-bc5ff0ec103b",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 224
        }
      },
      "source": [
        "!wget https://raw.githubusercontent.com/zygmuntz/goodbooks-10k/master/books.csv"
      ],
      "execution_count": null,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "--2020-10-18 20:26:25--  https://raw.githubusercontent.com/zygmuntz/goodbooks-10k/master/books.csv\n",
            "Resolving raw.githubusercontent.com (raw.githubusercontent.com)... 151.101.0.133, 151.101.64.133, 151.101.128.133, ...\n",
            "Connecting to raw.githubusercontent.com (raw.githubusercontent.com)|151.101.0.133|:443... connected.\n",
            "HTTP request sent, awaiting response... 200 OK\n",
            "Length: 3286659 (3.1M) [text/plain]\n",
            "Saving to: ‘books.csv’\n",
            "\n",
            "books.csv           100%[===================>]   3.13M  --.-KB/s    in 0.1s    \n",
            "\n",
            "2020-10-18 20:26:25 (25.4 MB/s) - ‘books.csv’ saved [3286659/3286659]\n",
            "\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "DawSG98zWFOQ"
      },
      "source": [
        "import pandas as pd\n",
        "books = pd.read_csv('books.csv', index_col=0)"
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "o8HTfPwRW8F_",
        "outputId": "cb39a8a2-f237-411c-9c9d-c9e291fdf0dd",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 459
        }
      },
      "source": [
        "books.head()"
      ],
      "execution_count": null,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/html": [
              "<div>\n",
              "<style scoped>\n",
              "    .dataframe tbody tr th:only-of-type {\n",
              "        vertical-align: middle;\n",
              "    }\n",
              "\n",
              "    .dataframe tbody tr th {\n",
              "        vertical-align: top;\n",
              "    }\n",
              "\n",
              "    .dataframe thead th {\n",
              "        text-align: right;\n",
              "    }\n",
              "</style>\n",
              "<table border=\"1\" class=\"dataframe\">\n",
              "  <thead>\n",
              "    <tr style=\"text-align: right;\">\n",
              "      <th></th>\n",
              "      <th>goodreads_book_id</th>\n",
              "      <th>best_book_id</th>\n",
              "      <th>work_id</th>\n",
              "      <th>books_count</th>\n",
              "      <th>isbn</th>\n",
              "      <th>isbn13</th>\n",
              "      <th>authors</th>\n",
              "      <th>original_publication_year</th>\n",
              "      <th>original_title</th>\n",
              "      <th>title</th>\n",
              "      <th>language_code</th>\n",
              "      <th>average_rating</th>\n",
              "      <th>ratings_count</th>\n",
              "      <th>work_ratings_count</th>\n",
              "      <th>work_text_reviews_count</th>\n",
              "      <th>ratings_1</th>\n",
              "      <th>ratings_2</th>\n",
              "      <th>ratings_3</th>\n",
              "      <th>ratings_4</th>\n",
              "      <th>ratings_5</th>\n",
              "      <th>image_url</th>\n",
              "      <th>small_image_url</th>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>book_id</th>\n",
              "      <th></th>\n",
              "      <th></th>\n",
              "      <th></th>\n",
              "      <th></th>\n",
              "      <th></th>\n",
              "      <th></th>\n",
              "      <th></th>\n",
              "      <th></th>\n",
              "      <th></th>\n",
              "      <th></th>\n",
              "      <th></th>\n",
              "      <th></th>\n",
              "      <th></th>\n",
              "      <th></th>\n",
              "      <th></th>\n",
              "      <th></th>\n",
              "      <th></th>\n",
              "      <th></th>\n",
              "      <th></th>\n",
              "      <th></th>\n",
              "      <th></th>\n",
              "      <th></th>\n",
              "    </tr>\n",
              "  </thead>\n",
              "  <tbody>\n",
              "    <tr>\n",
              "      <th>1</th>\n",
              "      <td>2767052</td>\n",
              "      <td>2767052</td>\n",
              "      <td>2792775</td>\n",
              "      <td>272</td>\n",
              "      <td>439023483</td>\n",
              "      <td>9.780439e+12</td>\n",
              "      <td>Suzanne Collins</td>\n",
              "      <td>2008.0</td>\n",
              "      <td>The Hunger Games</td>\n",
              "      <td>The Hunger Games (The Hunger Games, #1)</td>\n",
              "      <td>eng</td>\n",
              "      <td>4.34</td>\n",
              "      <td>4780653</td>\n",
              "      <td>4942365</td>\n",
              "      <td>155254</td>\n",
              "      <td>66715</td>\n",
              "      <td>127936</td>\n",
              "      <td>560092</td>\n",
              "      <td>1481305</td>\n",
              "      <td>2706317</td>\n",
              "      <td>https://images.gr-assets.com/books/1447303603m...</td>\n",
              "      <td>https://images.gr-assets.com/books/1447303603s...</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>2</th>\n",
              "      <td>3</td>\n",
              "      <td>3</td>\n",
              "      <td>4640799</td>\n",
              "      <td>491</td>\n",
              "      <td>439554934</td>\n",
              "      <td>9.780440e+12</td>\n",
              "      <td>J.K. Rowling, Mary GrandPré</td>\n",
              "      <td>1997.0</td>\n",
              "      <td>Harry Potter and the Philosopher's Stone</td>\n",
              "      <td>Harry Potter and the Sorcerer's Stone (Harry P...</td>\n",
              "      <td>eng</td>\n",
              "      <td>4.44</td>\n",
              "      <td>4602479</td>\n",
              "      <td>4800065</td>\n",
              "      <td>75867</td>\n",
              "      <td>75504</td>\n",
              "      <td>101676</td>\n",
              "      <td>455024</td>\n",
              "      <td>1156318</td>\n",
              "      <td>3011543</td>\n",
              "      <td>https://images.gr-assets.com/books/1474154022m...</td>\n",
              "      <td>https://images.gr-assets.com/books/1474154022s...</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>3</th>\n",
              "      <td>41865</td>\n",
              "      <td>41865</td>\n",
              "      <td>3212258</td>\n",
              "      <td>226</td>\n",
              "      <td>316015849</td>\n",
              "      <td>9.780316e+12</td>\n",
              "      <td>Stephenie Meyer</td>\n",
              "      <td>2005.0</td>\n",
              "      <td>Twilight</td>\n",
              "      <td>Twilight (Twilight, #1)</td>\n",
              "      <td>en-US</td>\n",
              "      <td>3.57</td>\n",
              "      <td>3866839</td>\n",
              "      <td>3916824</td>\n",
              "      <td>95009</td>\n",
              "      <td>456191</td>\n",
              "      <td>436802</td>\n",
              "      <td>793319</td>\n",
              "      <td>875073</td>\n",
              "      <td>1355439</td>\n",
              "      <td>https://images.gr-assets.com/books/1361039443m...</td>\n",
              "      <td>https://images.gr-assets.com/books/1361039443s...</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>4</th>\n",
              "      <td>2657</td>\n",
              "      <td>2657</td>\n",
              "      <td>3275794</td>\n",
              "      <td>487</td>\n",
              "      <td>61120081</td>\n",
              "      <td>9.780061e+12</td>\n",
              "      <td>Harper Lee</td>\n",
              "      <td>1960.0</td>\n",
              "      <td>To Kill a Mockingbird</td>\n",
              "      <td>To Kill a Mockingbird</td>\n",
              "      <td>eng</td>\n",
              "      <td>4.25</td>\n",
              "      <td>3198671</td>\n",
              "      <td>3340896</td>\n",
              "      <td>72586</td>\n",
              "      <td>60427</td>\n",
              "      <td>117415</td>\n",
              "      <td>446835</td>\n",
              "      <td>1001952</td>\n",
              "      <td>1714267</td>\n",
              "      <td>https://images.gr-assets.com/books/1361975680m...</td>\n",
              "      <td>https://images.gr-assets.com/books/1361975680s...</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>5</th>\n",
              "      <td>4671</td>\n",
              "      <td>4671</td>\n",
              "      <td>245494</td>\n",
              "      <td>1356</td>\n",
              "      <td>743273567</td>\n",
              "      <td>9.780743e+12</td>\n",
              "      <td>F. Scott Fitzgerald</td>\n",
              "      <td>1925.0</td>\n",
              "      <td>The Great Gatsby</td>\n",
              "      <td>The Great Gatsby</td>\n",
              "      <td>eng</td>\n",
              "      <td>3.89</td>\n",
              "      <td>2683664</td>\n",
              "      <td>2773745</td>\n",
              "      <td>51992</td>\n",
              "      <td>86236</td>\n",
              "      <td>197621</td>\n",
              "      <td>606158</td>\n",
              "      <td>936012</td>\n",
              "      <td>947718</td>\n",
              "      <td>https://images.gr-assets.com/books/1490528560m...</td>\n",
              "      <td>https://images.gr-assets.com/books/1490528560s...</td>\n",
              "    </tr>\n",
              "  </tbody>\n",
              "</table>\n",
              "</div>"
            ],
            "text/plain": [
              "         goodreads_book_id  ...                                    small_image_url\n",
              "book_id                     ...                                                   \n",
              "1                  2767052  ...  https://images.gr-assets.com/books/1447303603s...\n",
              "2                        3  ...  https://images.gr-assets.com/books/1474154022s...\n",
              "3                    41865  ...  https://images.gr-assets.com/books/1361039443s...\n",
              "4                     2657  ...  https://images.gr-assets.com/books/1361975680s...\n",
              "5                     4671  ...  https://images.gr-assets.com/books/1490528560s...\n",
              "\n",
              "[5 rows x 22 columns]"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 5
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "IUeJXtMpXKOj"
      },
      "source": [
        "def get_book_titles(book_ids):\n",
        "  '''Get book titles by book ids\n",
        "  Example:\n",
        "  --------\n",
        "  >> get_book_titles(1)\n",
        "  ['The Hunger Games (The Hunger Games, #1)']\n",
        "  '''\n",
        "  if isinstance(book_ids, int):\n",
        "    book_ids = [book_ids]\n",
        "  titles = []\n",
        "  for book_id in book_ids:\n",
        "    titles.append(books.loc[book_id, 'title'])\n",
        "  return titles"
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "pZlOY_lC4Mkg"
      },
      "source": [
        "data = _get_dataset()\n",
        "interactions = Interactions(*data)"
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "AMi2kZX_VRkk",
        "outputId": "fb5fedc5-27b8-438c-e02f-7d814012470c",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 102
        }
      },
      "source": [
        "data"
      ],
      "execution_count": null,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "(array([    1,     2,     2, ..., 49925, 49925, 49925], dtype=int32),\n",
              " array([ 258, 4081,  260, ...,  722,  949, 1023], dtype=int32),\n",
              " array([5., 4., 5., ..., 4., 5., 4.], dtype=float32),\n",
              " array([      0,       1,       2, ..., 5976476, 5976477, 5976478],\n",
              "       dtype=int32))"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 8
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "BKtSQq047pju",
        "outputId": "9fdfda85-066f-4b62-c54a-82b45aac6b4e",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 34
        }
      },
      "source": [
        "print(interactions)"
      ],
      "execution_count": null,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "<Interactions dataset (53425 users x 10001 items x 5976479 interactions)>\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "By5n99R57yrp"
      },
      "source": [
        "import torch\n",
        "\n",
        "from spotlight.factorization.explicit import ExplicitFactorizationModel\n",
        "\n",
        "model = ExplicitFactorizationModel(loss='regression',\n",
        "                                   embedding_dim=128,  # latent dimensionality\n",
        "                                   n_iter=10,  # number of epochs of training\n",
        "                                   batch_size=1024,  # minibatch size\n",
        "                                   l2=1e-9,  # strength of L2 regularization\n",
        "                                   learning_rate=1e-3,\n",
        "                                   use_cuda=torch.cuda.is_available())\n"
      ],
      "execution_count": 30,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "fO9GM0Zx7z_x"
      },
      "source": [
        "from spotlight.cross_validation import random_train_test_split\n",
        "import numpy as np\n",
        "\n",
        "train, test = random_train_test_split(interactions, random_state=np.random.RandomState(42))\n"
      ],
      "execution_count": 31,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "Nk7jhvaZ8FsD",
        "outputId": "0c561ba5-6557-4a3e-960c-628f335fadda",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 68
        }
      },
      "source": [
        "print('Split into \\n {} and \\n {}.'.format(train, test))"
      ],
      "execution_count": 32,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "Split into \n",
            " <Interactions dataset (53425 users x 10001 items x 4781183 interactions)> and \n",
            " <Interactions dataset (53425 users x 10001 items x 1195296 interactions)>.\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "ekZwgODA8Jz0",
        "outputId": "e39cfd35-d737-4635-c84a-93194f67c5ec",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 238
        }
      },
      "source": [
        "model.fit(train, verbose=True)\n",
        "from spotlight.evaluation import rmse_score, precision_recall_score\n",
        "\n",
        "train_rmse = rmse_score(model, train)\n",
        "test_rmse = rmse_score(model, test)\n",
        "train_precision, train_recall = precision_recall_score(model, train, k=5)\n",
        "test_precision, test_recall = precision_recall_score(model, test, k=5)\n",
        "\n",
        "print('Train RMSE {:.3f}, test RMSE {:.3f}'.format(train_rmse, test_rmse))\n",
        "print(\n",
        "    'mean train precision at 5: {:.3f}'.format(\n",
        "        train_precision.mean()\n",
        "))\n",
        "print(\n",
        "    'mean test precision at 5: {:.3f}'.format(\n",
        "        test_precision.mean()\n",
        "))"
      ],
      "execution_count": 33,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "Epoch 0: loss 2.762984432512994\n",
            "Epoch 1: loss 0.7377435095815638\n",
            "Epoch 2: loss 0.6588062686379001\n",
            "Epoch 3: loss 0.5621107913633485\n",
            "Epoch 4: loss 0.44322063551469837\n",
            "Epoch 5: loss 0.32800119822681334\n",
            "Epoch 6: loss 0.2381617845189648\n",
            "Epoch 7: loss 0.1754616707276226\n",
            "Epoch 8: loss 0.1336526694912982\n",
            "Epoch 9: loss 0.10600318515422003\n",
            "Train RMSE 0.265, test RMSE 0.965\n",
            "mean train precision at 5: 0.027\n",
            "mean test precision at 5: 0.020\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "Fs9I0Vk0oHiT"
      },
      "source": [
        "# explaining predictions. Based on https://github.com/lyst/lightfm/blob/master/examples/quickstart/quickstart.ipynb\n",
        "\n",
        "def sample_recommendation(model, user_ids, train, item_labels):\n",
        "    '''Give recommendations for users given a model and explain recommendations.\n",
        "    '''\n",
        "    n_users, n_items = train.shape\n",
        "\n",
        "    for user_id in user_ids:\n",
        "        known_positives = item_labels[train[user_id].indices]\n",
        "        \n",
        "        scores = model.predict(user_id, np.arange(n_items))\n",
        "        top_items = item_labels[np.argsort(-scores)]\n",
        "        \n",
        "        print(\"User %s\" % user_id)\n",
        "        print(\"     Known positives:\")\n",
        "        \n",
        "        for x in known_positives[:3]:\n",
        "            print(\"        %s\" % x)\n",
        "\n",
        "        print(\"     Recommended:\")\n",
        "        \n",
        "        for x in top_items[:3]:\n",
        "            print(\"        %s\" % x)"
      ],
      "execution_count": 34,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "TCHsBHOLoTgD",
        "outputId": "adb055f1-1e60-43c0-ed58-1b010c58779f",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 187
        }
      },
      "source": [
        "book_labels = get_book_titles(list(train.item_ids))\n",
        "book_labels[:10]"
      ],
      "execution_count": 35,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "[\"Ahab's Wife, or The Star-Gazer\",\n",
              " 'City of Glass (The Mortal Instruments, #3)',\n",
              " \"Enchanters' End Game (The Belgariad, #5)\",\n",
              " 'Frankenstein',\n",
              " 'The Atlantis Complex (Artemis Fowl, #7)',\n",
              " 'The Life and Times of the Thunderbolt Kid',\n",
              " 'A Game of Thrones (A Song of Ice and Fire, #1)',\n",
              " 'Disgrace',\n",
              " 'Beautiful Creatures (Caster Chronicles, #1)',\n",
              " 'The Alchemist']"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 35
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "OIi2bGhEoc5l",
        "outputId": "e1a1af78-76d4-4d00-f64a-770471af9a6c",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 476
        }
      },
      "source": [
        "sample_recommendation(model, [3, 9999, 15000], train.tocsr(), np.array(book_labels))"
      ],
      "execution_count": 36,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "User 3\n",
            "     Known positives:\n",
            "        The Atlantis Complex (Artemis Fowl, #7)\n",
            "        Sentinel (Covenant, #5)\n",
            "        The Devil Wears Prada (The Devil Wears Prada, #1)\n",
            "     Recommended:\n",
            "        Romeo and Juliet\n",
            "        Altered Carbon (Takeshi Kovacs, #1)\n",
            "        The Little Engine That Could\n",
            "User 9999\n",
            "     Known positives:\n",
            "        City of Glass (The Mortal Instruments, #3)\n",
            "        The Magicians' Guild (Black Magician Trilogy, #1)\n",
            "        Bridge to Terabithia\n",
            "     Recommended:\n",
            "        Darkness at Noon\n",
            "        Magyk (Septimus Heap, #1)\n",
            "        The Complete Stories and Poems\n",
            "User 15000\n",
            "     Known positives:\n",
            "        Enchanters' End Game (The Belgariad, #5)\n",
            "        The Life and Times of the Thunderbolt Kid\n",
            "        Beautiful Creatures (Caster Chronicles, #1)\n",
            "     Recommended:\n",
            "        Tales of a Fourth Grade Nothing (Fudge, #1)\n",
            "        Wizard and Glass (The Dark Tower, #4)\n",
            "        Plum Lovin' (Stephanie Plum, #12.5)\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "muIudpFLK_Q4",
        "outputId": "05edc387-8c95-4f3b-cdc5-6a774f860e5b",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 34
        }
      },
      "source": [
        "from spotlight.evaluation import precision_recall_score\n",
        "\n",
        "train_prs = precision_recall_score(model, train, k=5)\n",
        "test_prs = precision_recall_score(model, test, k=5)\n",
        "\n",
        "print('Train PRS {:.3f}, test PRS {:.3f}'.format(train_rmse, test_rmse))"
      ],
      "execution_count": 37,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "Train PRS 0.265, test PRS 0.965\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "0HmxqtCuug8a",
        "outputId": "01a326ed-e1c0-4593-b645-f63338f1b004",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 51
        }
      },
      "source": [
        "print(\n",
        "    'mean train precision at 5: {:.3f}'.format(\n",
        "        train_prs[0].mean()\n",
        "))\n",
        "print(\n",
        "    'mean test precision at 5: {:.3f}'.format(\n",
        "        test_prs[0].mean()\n",
        "))"
      ],
      "execution_count": 38,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "mean train precision at 5: 0.027\n",
            "mean test precision at 5: 0.020\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "UBpy156e9vGq",
        "outputId": "70ae3828-9430-4d12-8787-9d4e3513d5e4",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 326
        }
      },
      "source": [
        "!pip install lightfm"
      ],
      "execution_count": 47,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "Collecting lightfm\n",
            "\u001b[?25l  Downloading https://files.pythonhosted.org/packages/e9/8e/5485ac5a8616abe1c673d1e033e2f232b4319ab95424b42499fabff2257f/lightfm-1.15.tar.gz (302kB)\n",
            "\r\u001b[K     |█                               | 10kB 23.9MB/s eta 0:00:01\r\u001b[K     |██▏                             | 20kB 6.2MB/s eta 0:00:01\r\u001b[K     |███▎                            | 30kB 7.5MB/s eta 0:00:01\r\u001b[K     |████▍                           | 40kB 7.6MB/s eta 0:00:01\r\u001b[K     |█████▍                          | 51kB 6.8MB/s eta 0:00:01\r\u001b[K     |██████▌                         | 61kB 8.0MB/s eta 0:00:01\r\u001b[K     |███████▋                        | 71kB 8.4MB/s eta 0:00:01\r\u001b[K     |████████▊                       | 81kB 8.9MB/s eta 0:00:01\r\u001b[K     |█████████▊                      | 92kB 8.7MB/s eta 0:00:01\r\u001b[K     |██████████▉                     | 102kB 9.3MB/s eta 0:00:01\r\u001b[K     |████████████                    | 112kB 9.3MB/s eta 0:00:01\r\u001b[K     |█████████████                   | 122kB 9.3MB/s eta 0:00:01\r\u001b[K     |██████████████                  | 133kB 9.3MB/s eta 0:00:01\r\u001b[K     |███████████████▏                | 143kB 9.3MB/s eta 0:00:01\r\u001b[K     |████████████████▎               | 153kB 9.3MB/s eta 0:00:01\r\u001b[K     |█████████████████▍              | 163kB 9.3MB/s eta 0:00:01\r\u001b[K     |██████████████████▍             | 174kB 9.3MB/s eta 0:00:01\r\u001b[K     |███████████████████▌            | 184kB 9.3MB/s eta 0:00:01\r\u001b[K     |████████████████████▋           | 194kB 9.3MB/s eta 0:00:01\r\u001b[K     |█████████████████████▊          | 204kB 9.3MB/s eta 0:00:01\r\u001b[K     |██████████████████████▊         | 215kB 9.3MB/s eta 0:00:01\r\u001b[K     |███████████████████████▉        | 225kB 9.3MB/s eta 0:00:01\r\u001b[K     |█████████████████████████       | 235kB 9.3MB/s eta 0:00:01\r\u001b[K     |██████████████████████████      | 245kB 9.3MB/s eta 0:00:01\r\u001b[K     |███████████████████████████     | 256kB 9.3MB/s eta 0:00:01\r\u001b[K     |████████████████████████████▏   | 266kB 9.3MB/s eta 0:00:01\r\u001b[K     |█████████████████████████████▎  | 276kB 9.3MB/s eta 0:00:01\r\u001b[K     |██████████████████████████████▍ | 286kB 9.3MB/s eta 0:00:01\r\u001b[K     |███████████████████████████████▍| 296kB 9.3MB/s eta 0:00:01\r\u001b[K     |████████████████████████████████| 307kB 9.3MB/s \n",
            "\u001b[?25hRequirement already satisfied: numpy in /usr/local/lib/python3.6/dist-packages (from lightfm) (1.18.5)\n",
            "Requirement already satisfied: scipy>=0.17.0 in /usr/local/lib/python3.6/dist-packages (from lightfm) (1.4.1)\n",
            "Requirement already satisfied: requests in /usr/local/lib/python3.6/dist-packages (from lightfm) (2.23.0)\n",
            "Requirement already satisfied: chardet<4,>=3.0.2 in /usr/local/lib/python3.6/dist-packages (from requests->lightfm) (3.0.4)\n",
            "Requirement already satisfied: urllib3!=1.25.0,!=1.25.1,<1.26,>=1.21.1 in /usr/local/lib/python3.6/dist-packages (from requests->lightfm) (1.24.3)\n",
            "Requirement already satisfied: certifi>=2017.4.17 in /usr/local/lib/python3.6/dist-packages (from requests->lightfm) (2020.6.20)\n",
            "Requirement already satisfied: idna<3,>=2.5 in /usr/local/lib/python3.6/dist-packages (from requests->lightfm) (2.10)\n",
            "Building wheels for collected packages: lightfm\n",
            "  Building wheel for lightfm (setup.py) ... \u001b[?25l\u001b[?25hdone\n",
            "  Created wheel for lightfm: filename=lightfm-1.15-cp36-cp36m-linux_x86_64.whl size=709137 sha256=33ac00a0cdcb0393e76e2872cad626099fd1a69033af124ee3163a08930640ab\n",
            "  Stored in directory: /root/.cache/pip/wheels/eb/bb/ac/188385a5da6627956be5d9663928483b36da576149ab5b8f79\n",
            "Successfully built lightfm\n",
            "Installing collected packages: lightfm\n",
            "Successfully installed lightfm-1.15\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "o6E15CB99xr9",
        "outputId": "85eb9969-cbdb-4c35-d3dd-048c33280e59",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 34
        }
      },
      "source": [
        "# from tutorial at https://github.com/lyst/lightfm\n",
        "from lightfm import LightFM\n",
        "from lightfm.evaluation import precision_at_k\n",
        "\n",
        "# Load the MovieLens 100k dataset. Only five\n",
        "# star ratings are treated as positive.\n",
        "#data = fetch_movielens(min_rating=5.0)\n",
        "\n",
        "# Instantiate and train the model\n",
        "model = LightFM(loss='warp')\n",
        "model.fit(train.tocoo(), epochs=30, num_threads=2)"
      ],
      "execution_count": 53,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "<lightfm.lightfm.LightFM at 0x7fe92ab435c0>"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 53
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "nzXuYWpBPmby"
      },
      "source": [
        "# Evaluate the trained model\n",
        "test_precision = precision_at_k(model, test.tocoo(), k=5)"
      ],
      "execution_count": 54,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "Djh5X7d5PqTg",
        "outputId": "04139def-9bc7-4d5a-a01f-3f9f5dab383b",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 34
        }
      },
      "source": [
        "test_precision  # .mean()"
      ],
      "execution_count": 55,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "array([0.6, 0. , 0. , ..., 0.2, 0.2, 0.4], dtype=float32)"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 55
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "GhIKv53VSvnr",
        "outputId": "9d5945c9-c010-4d11-e788-b07c049a08a4",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 34
        }
      },
      "source": [
        "test_precision.mean()"
      ],
      "execution_count": 56,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "0.11688069"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 56
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "JmARW1jjS7y6",
        "outputId": "91720f41-3e50-45c4-e2d0-63cdd0c8cec5",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 476
        }
      },
      "source": [
        "sample_recommendation(model, [3, 9999, 15000], train.tocsr(), np.array(book_labels))"
      ],
      "execution_count": 57,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "User 3\n",
            "     Known positives:\n",
            "        The Atlantis Complex (Artemis Fowl, #7)\n",
            "        Sentinel (Covenant, #5)\n",
            "        The Devil Wears Prada (The Devil Wears Prada, #1)\n",
            "     Recommended:\n",
            "        The Life and Times of the Thunderbolt Kid\n",
            "        The Atlantis Complex (Artemis Fowl, #7)\n",
            "        Beautiful Creatures (Caster Chronicles, #1)\n",
            "User 9999\n",
            "     Known positives:\n",
            "        City of Glass (The Mortal Instruments, #3)\n",
            "        The Magicians' Guild (Black Magician Trilogy, #1)\n",
            "        Bridge to Terabithia\n",
            "     Recommended:\n",
            "        City of Glass (The Mortal Instruments, #3)\n",
            "        Enchanters' End Game (The Belgariad, #5)\n",
            "        Bridge to Terabithia\n",
            "User 15000\n",
            "     Known positives:\n",
            "        Enchanters' End Game (The Belgariad, #5)\n",
            "        The Life and Times of the Thunderbolt Kid\n",
            "        Beautiful Creatures (Caster Chronicles, #1)\n",
            "     Recommended:\n",
            "        Where the Heart Is\n",
            "        Gone Girl\n",
            "        Tangled (Tangled, #1)\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "gDBItHUWQZo0"
      },
      "source": [
        ""
      ],
      "execution_count": 57,
      "outputs": []
    }
  ]
}